package org.lm2a.client.alfa;

/******************************************************************************\
**                                                                            **
** Licensed Materials - Property of IBM                                       **
** IBM Toolkit for MPEG-4                                                     **
** Copyright IBM Corp. 1998-2005  All Rights Reserved                         **
**                                                                            **
\******************************************************************************/

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.URL;

import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.JLabel;

import player.PlayerAdapter;
import player.PlayerControl;
import player.PlayerControlPanel;
import player.PlayerControlPanelFactory;
import player.PlayerFactory;

/*******************************************************************************
 * IBM Toolkit for MPEG-4 Sample Player application for Swing. This code has
 * been adapted from the M4AppSample which was written using the AWT for the UI.
 *
 */
public class SynM4XClient extends JFrame
{
  /**
	 * 
	 */
	private static final long	serialVersionUID	= 1L;
	private final static String kPlayerName = "IBM Toolkit for MPEG-4 with Resume Control Player";
	private final static String RESUMESERVER = "localhost:5678";

  static
  {
    // Set the Swing UI to have the look and feel of the system its running on. We do this here in
    // a static initialization block so its done ahead of the menu and menu items being created
    // when the class is instantiated below.
    //
    try
    {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch (Exception ignored) {/* ignored - will use default look and feel should this fail */}
  }

  // The menus for the player; indented to show highlight the actual layout
  //
  private JMenu                fileMenu          = new JMenu("File");
  private JMenuItem            openMenuItem        = new JMenuItem("Open...");
  private JMenuItem            closeMenuItem       = new JMenuItem("Close");
  private JMenuItem            exitMenuItem        = new JMenuItem("Exit");

  private JMenu                viewMenu          = new JMenu("View");
  private JCheckBoxMenuItem    autosizeMenuItem    = new JCheckBoxMenuItem("Size window to new content");
  private JCheckBoxMenuItem    scaleMenuItem       = new JCheckBoxMenuItem("Scale content to window");
  private JCheckBoxMenuItem    speedScaleMenuItem  = new JCheckBoxMenuItem("Scaling; speed (vs. quality)");
  private JMenu                sizeMenu            = new JMenu("Window size");
  private JMenuItem            size50MenuItem        = new JMenuItem("50%");
  private JMenuItem            size100MenuItem       = new JMenuItem("100%");
  private JMenuItem            size200MenuItem       = new JMenuItem("200%");
  private JMenuItem            sizeHalfMenuItem      = new JMenuItem("x \u00BD");
  private JMenuItem            sizeTwiceMenuItem     = new JMenuItem("x 2");
  private JCheckBoxMenuItem    ctlBarMenuItem      = new JCheckBoxMenuItem("Control Bar");

  private JMenu                playMenu          = new JMenu("Play");
  private JMenuItem            playPauseMenuItem   = new JMenuItem("Play/Pause");
  private JMenuItem            playPauseRCMenuItem   = new JMenuItem("Reconnecting");
  private JMenuItem            stopMenuItem        = new JMenuItem("Stop");
  private JMenu                atDurActMenu        = new JMenu("At duration");
  private JRadioButtonMenuItem endContMenuItem       = new JRadioButtonMenuItem("Continue");
  private JRadioButtonMenuItem endStopMenuItem       = new JRadioButtonMenuItem("Stop");
  private JRadioButtonMenuItem endRptMenuItem        = new JRadioButtonMenuItem("Restart");
  private JCheckBoxMenuItem    muteMenuItem        = new JCheckBoxMenuItem("Mute");

  private PlayerControl      m4Player;         // This is the control interface for the player
  private PlayerControlPanel m4PlayerPanel;    // This is for the control panel bar

  private boolean playerAdded;                 // True when player renderer component is added to our frame
  //private Escuchador escuchador = new Escuchador();
  private static SynchronizedResumeControlHTTP synchronizedResumeControlHTTP; 
  static String archivo;
  private M4AppPlayerAdapter m4apa;
  private boolean stateChangedByRC = false;
  private JLabel reconnecting = new JLabel("Reconnecting");
  /*****************************************************************************
   * The constructor creates the player, sets up listeners, sets up
   * behavior using the player control, adds a player control panel
   * and shows the application
   */
  public SynM4XClient()
  {
    // Create the MPEG-4 player and add our listener class that has been derived from the PlayerAdapter
    //
    /*
     * // This commented code is the orginal code for this sample used with IBM Toolkit For MPEG-4
     * // versions up to 1.2.6. In version 1.2.6 a new lightweight rendering player was introduced and
     * // that is now created below. With that we can put lightwight swing components over the player
     * // and we don't need anymore the line of code to set JPopupMenu so menus come above the player.
     * // The heavweight version can still be used, hence the lines of code have been kept here to show
     * // how its done for that case.
     *
     * m4Player = PlayerFactory.createMPEG4Player();
     *
     * // Make sure we use have menus that will come up over the heavyweight player component
     * //
     * javax.swing.JPopupMenu.setDefaultLightWeightPopupEnabled(false);
     *
     */

    m4Player = PlayerFactory.createLightweightMPEG4Player();  // From 1.2.6 we can now create a lightweight player
    m4apa = new M4AppPlayerAdapter();
    m4Player.addListener(m4apa);
	m4Player.addListener(synchronizedResumeControlHTTP);
    // This is to allow the frame to close when we click the close button
    //
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {exit();}
    });

    // This is for when we are showing the title in the main frame to update as it resizes
    //
    addComponentListener(new ComponentAdapter() {
      public void componentResized(ComponentEvent e) {if (!playerAdded) repaint();}
    });

    // Put in our custom pane which will show our text 'logo'
    //
    setContentPane(new MyJPanel());

    // We use a border layout with the player's renderer component in the center and the control panel
    // to the south
    //
    getContentPane().setLayout(new BorderLayout());

    // Create the menus bar and setup the player
    //
    createMenuBar();
    //
    m4Player.setAutoSize(false);                     // We don't want the forced autosize, we do any resize ourself
    m4Player.setScaling(scaleMenuItem.getState());   // Scaling is set as per the menu state
    m4Player.setSpeedScaling(speedScaleMenuItem.getState());
    setEndAction(PlayerControl.END_ACTION_CONTINUE); // We set a default end behavior to carry on playing
    endContMenuItem.setSelected(true);
    atDurActMenu.setEnabled(false);                  // wait until we have content to enable this (see M4AppPlayerAdapter)
    m4Player.setMute(muteMenuItem.getState());       // Mute is as per the menu state

    // Create a control panel and set the menus to match
    //
    m4PlayerPanel = PlayerControlPanelFactory.createPlayerControlPanel("Basic", m4Player);
    if (m4PlayerPanel != null)
    {
      m4PlayerPanel.setBackground(Color.lightGray);
      showControlBar(true);
      ctlBarMenuItem.setEnabled(true);
      ctlBarMenuItem.setState(true);
    }

    // Lastly put the sample into the window title and show the player at a reasonable starting size
    //
    setTitle(kPlayerName);
    setSize(360, 280);
    show();
  }

  /*****************************************************************************
   * Creates the menus bar, sets up listeners for the menus and initializes
   * menus according to an initial setup (Note: some menu settings could be
   * saved as persistent preferences and reloaded, but that is beyond the scope
   * of this sample player)
   */
  private void createMenuBar()
  {
    JMenuBar  mb = new JMenuBar();

    mb.add(fileMenu);
    //
    openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, java.awt.Event.CTRL_MASK));
    openMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {open();}
    });
    fileMenu.add(openMenuItem);
    //
    closeMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {close();}
    });
    fileMenu.add(closeMenuItem);
    //
    fileMenu.addSeparator();
    exitMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {exit();}
    });
    fileMenu.add(exitMenuItem);

    mb.add(viewMenu);
    //
    viewMenu.add(autosizeMenuItem);
    //
    scaleMenuItem.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {m4Player.setScaling(scaleMenuItem.getState());}
    });
    viewMenu.add(scaleMenuItem);
    //
    speedScaleMenuItem.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {m4Player.setSpeedScaling(speedScaleMenuItem.getState());}
    });
    viewMenu.add(speedScaleMenuItem);
    //
    viewMenu.add(sizeMenu);
    //
    sizeMenu.add(size50MenuItem);
    size50MenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_0, java.awt.Event.CTRL_MASK));
    size50MenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {setSizePercent(50);}
    });
    //
    sizeMenu.add(size100MenuItem);
    size100MenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, java.awt.Event.CTRL_MASK));
    size100MenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {setSizePercent(100);}
    });
    //
    sizeMenu.add(size200MenuItem);
    size200MenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, java.awt.Event.CTRL_MASK));
    size200MenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {setSizePercent(200);}
    });
    //
    sizeMenu.addSeparator();
    sizeMenu.add(sizeHalfMenuItem);
    sizeHalfMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, java.awt.Event.CTRL_MASK));
    sizeHalfMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {setSizeActual(50);}
    });
    //
    sizeMenu.add(sizeTwiceMenuItem);
    sizeTwiceMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, java.awt.Event.CTRL_MASK));
    sizeTwiceMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {setSizeActual(200);}
    });
    //
    viewMenu.addSeparator();
    viewMenu.add(ctlBarMenuItem);
    ctlBarMenuItem.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {showControlBar(ctlBarMenuItem.getState());}
    });

    mb.add(playMenu);
    //
    playMenu.add(playPauseMenuItem);
    playPauseMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, java.awt.Event.CTRL_MASK));
    playPauseMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {playPauseAction();}
    });
    //
    playMenu.add(stopMenuItem);
    stopMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, java.awt.Event.CTRL_MASK));
    stopMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {stopAction();}
    });
    //
    playMenu.addSeparator();
    playMenu.add(atDurActMenu);
    //
    atDurActMenu.add(endContMenuItem);
    endContMenuItem.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {setEndAction(PlayerControl.END_ACTION_CONTINUE);}
    });
    //
    atDurActMenu.add(endStopMenuItem);
    endStopMenuItem.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {setEndAction(PlayerControl.END_ACTION_STOP);}
    });
    //
    atDurActMenu.add(endRptMenuItem);
    endRptMenuItem.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {setEndAction(PlayerControl.END_ACTION_REPEAT);}
    });
    ButtonGroup bg = new ButtonGroup(); // The end action menus are to act as a radio button group
    bg.add(endContMenuItem);
    bg.add(endStopMenuItem);
    bg.add(endRptMenuItem);
    //
    playMenu.addSeparator();
    playMenu.add(muteMenuItem);
    muteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, java.awt.Event.CTRL_MASK));
    muteMenuItem.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {m4Player.setMute(muteMenuItem.getState());}
    });

    closeMenuItem.setEnabled(false);
    autosizeMenuItem.setState(true);
    sizeMenu.setEnabled(false);
    ctlBarMenuItem.setEnabled(false);
    playPauseMenuItem.setEnabled(false);
    stopMenuItem.setEnabled(false);

    setJMenuBar(mb);
  }

  /*****************************************************************************
   * Main entry point for the sample application.  We can pass a url from the
   * command line here; a local file or remote server e.g.  rtsp:// type url.
   * With this sample application passing a remote url here is the only way to
   * access remote content as this sample player has only a file open dialog.
   * (An OpenURL dialog could be added but again is beyond the scope of this
   * sample).
   *
   * @param args A string as a url point to media content
   */
  public static void main(String[] args)
  {
    // Create a new instance of our application
    SynM4XClient app = new SynM4XClient();
    if (args.length > 0)
    {
//      app.openPlayUrl(args[0]);  // invoke content directly from the command line
     archivo = args[0];
     app.new UsaResumeControl(archivo).start();
     try {
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
     app.openPlayUrl(archivo);  // invoke content directly from the command line

    }
  }

  /*****************************************************************************
   * This opens and plays the content referenced by the url. The
   * player renderer component is added if it has not already been added.
   * (i.e. we can Open a new content without closing the prior one).
   *
   * @param url    String referencing the content e.g. myfile.mp4,
   *               rtsp://myserver.com/myfile.mp4
   */
  private void openPlayUrl(String url)
  {
    // Stop & close any playback that may be running still
    //
    m4Player.stopUrl();

    try
    {
      // We title our window as per the content and added the player renderer
      // component if needed. Now we have the player added we can enable the size
      // menu to allow the content display size to be set.
      //
      setTitle(url);
      if (!playerAdded)
      {
        getContentPane().add("Center", m4Player.getRendererComponent());
        playerAdded = true;
        sizeMenu.setEnabled(true);
        validate();
      }


      //m4Player.open(url);
      URL urlTarget = new URL(archivo);
      String protocol = urlTarget.getProtocol();
      String filenameTarget = urlTarget.getFile();
      System.out.println("openPlayUrl(String url):"+protocol+"://"+RESUMESERVER+filenameTarget);
      System.out.println("openPlayUrl(String url) URL:"+url);
      m4Player.open(protocol+"://"+RESUMESERVER+filenameTarget);
      //m4Player.open("http://localhost:5678/sm/IBMAudioVideo.m4x");

      m4Player.start();
    }
    catch (Exception e)
    {
      m4Player.stopUrl();                  // Stop MPEG-4 player
      setTitle(e.toString());              // and set error in title bar
    }
  }

  /*****************************************************************************
   * Opens a local file from the file dialog and plays it
   */
  private void open()
  {
    JFileChooser openFileChooser = new JFileChooser();
    int retVal = openFileChooser.showOpenDialog(this);
    if (retVal == JFileChooser.APPROVE_OPTION)
    {
    	System.out.println(">>> openFileChooser.getSelectedFile().getAbsolutePath(): "+openFileChooser.getSelectedFile().getAbsolutePath());
        openPlayUrl(openFileChooser.getSelectedFile().getAbsolutePath());

    }
  }

  /*****************************************************************************
   * Stop playing and close any content, remove the player renderer
   * component. By closing the content we close any connection to it, e.g.. over
   * RTSP stopURL() will teardown and end the session.
   */
  private void close()
  {
    m4Player.stopUrl();
    getContentPane().remove(m4Player.getRendererComponent());
    sizeMenu.setEnabled(false);
    playerAdded = false;
    setTitle(kPlayerName);
  }

  /*****************************************************************************
   * We want to exit the application. Stop and close any content
   * that may be playing before exiting.
   */
  private void exit()
  {
    m4Player.stopUrl();
    dispose();
    System.exit(0);
  }

  /*****************************************************************************
   * This sets the player size as a ratio of the preferred content size. The
   * menus are not enabled unless there is a preferred size. An
   * optional preferred size is signalled in MPEG-4 content.
   *
   * @param percent Percentage of preferred size. Currently 50%, 100% and 200%
   */
  private void setSizePercent(int percent)
  {
    int wTarget = m4Player.getPreferredSceneSize().width;
    int hTarget = m4Player.getPreferredSceneSize().height;

    switch (percent)
    {
      case  50: wTarget /= 2; hTarget /= 2; break;
      case 100:                             break;
      case 200: wTarget *= 2; hTarget *= 2; break;
      default:  throw new IllegalArgumentException();
    }

    m4Player.setSize(wTarget, hTarget);
    validate();
    pack();
    pack();
  }

  /*****************************************************************************
   * This sets the player size as a ratio of its current size
   * whatever that is.
   *
   * @param percent Percentage of current size to set as new size (50% or 200%)
   */
  private void setSizeActual(int percent)
  {
    int wTarget = m4Player.getSize().width;
    int hTarget = m4Player.getSize().height;

    switch (percent)
    {
      case  50: wTarget /= 2; hTarget /= 2; break;
      case 200: wTarget *= 2; hTarget *= 2; break;
      default:  throw new IllegalArgumentException();
    }

    m4Player.setSize(wTarget, hTarget);
    validate();
    pack();
    pack();
  }

  /*****************************************************************************
   * This allows the control bar panel to be hidden or shown. If there
   * is no player renderer component added then the panel is added. If
   * the player renderer component has been added then the layout is
   * adjusted to keep the player size and add the panel.
   *
   * @param show   Set to true to show (add) the panel. False to hide (remove).
   */
  private void showControlBar(boolean show)
  {
    if (show)
    {
      getContentPane().add("South", m4PlayerPanel);
      m4PlayerPanel.attachToPlayer();
    }
    else
    {
      getContentPane().remove(m4PlayerPanel);
      m4PlayerPanel.detachFromPlayer();
    }
    if (playerAdded)
    {
      validate();
      pack();
      pack();
    }
  }

  private void rcReconnecting(boolean show)
  {
	  if(show){
		  showControlBar(false);  
		  getContentPane().add("South", reconnecting);
		  m4PlayerPanel.attachToPlayer();
	  }
	  else	{
		  showControlBar(true);  
	  }
	  if (playerAdded)
	    {
	     validate();
	     pack();
	     pack();
	    }
  }


  /*****************************************************************************
   * Handle our pause/play menu by playing (start()), or pausing or resuming
   * dependent on state. Menus are set as per state callbacks on our listener
   * class that extends PlayerAdapter.
   *
   * Error handling could be better; IOExceptions may occur for example if we
   * are using RTSP to communicate with a server over a network.
   */
  void playPauseAction()
  {
    try
    {
      switch (m4Player.getState())
      {
        case PlayerControl.STOPPED: m4Player.start();  break;
        case PlayerControl.PAUSED:  m4Player.resume(); break;
        case PlayerControl.PLAYING: m4Player.pause();  break;
      }
    }
    catch (IOException e){/*nothing*/}
    catch (IllegalStateException ie){/*nothing*/}
  }

  /*****************************************************************************
   * Handle our stop menu by stopping the player
   */
  void stopAction()
  {
    try
    {
      m4Player.stop();
    }
    catch (IOException e){/*nothing*/}
    catch (IllegalStateException ie){/*nothing*/}
  }

  /*****************************************************************************
   * Set the action that the player will take when the indicated duration of
   * the content is reached (if the content duration is indefinite/unknown
   * then this has no net effect)
   *
   * @param endAction The action to take
   */
  private void setEndAction(int endAction)
  {
    m4Player.setPlayerEndAction(endAction);
  }


  /*****************************************************************************
   * Extends the PlayerAdapter class so we can implement the methods only for
   * those events we are interested in here.
   * <p>
   * Since the methods here do UI actions we must ensure they are done on the
   * UI thread. To avoid any possibility of deadlock with the player, if/when
   * any methods need to call back to the player, we use the invokeLater()
   * rather than the invokedAndWait().
   *
   * @see player.PlayerAdapter
   * @see player.PlayerListener
   */
  private class M4AppPlayerAdapter extends PlayerAdapter
  {
    private boolean autoSized;  // Used when autosizing from content to content so we can prevent
                                // resizing when stopping/playing same content

    /***************************************************************************
     * Enable close/play/pause/stop menus according to state.  This allows us to
     * work in conjunction with the player control panel that can also affect
     * state.
     *
     * @param state  State as per PlayerControl i.e.. Closed. Playing etc
     *
     * @see player.PlayerListener#changedState(int)
     */
    public void changedState(final int state)
    {
      try
      {
        SwingUtilities.invokeLater(new Runnable() {
          public void run()
          {
            switch (state)
            {
              case PlayerControl.CLOSED:
                closeMenuItem.setEnabled(false);
                playPauseMenuItem.setEnabled(false);
                break;

              case PlayerControl.STOPPED:
                closeMenuItem.setEnabled(true);
                playPauseMenuItem.setEnabled(true);
                stopMenuItem.setEnabled(false);

                // The player is in Stopped state after the content is opened. In this
                // state we now have access to content specific info such as duration,
                // whether we can seek etc. Here this is used to show that we can
                // access if the content has a duration and enable/disable the
                // endAction menu accordingly (Note: since this is more a player
                // preference type behavior it may be preferable to keep the menu
                // enabled, whether specific content has duration or not, as it done
                // in our M4Play application. But this is shown here to illustrate
                // that certain info is available once the content is opened. See the
                // PlayerControl javadoc for more info.)
                //
                //
                atDurActMenu.setEnabled(m4Player.hasDuration());
                break;

              case PlayerControl.PLAYING:
                stopMenuItem.setEnabled(true);
                break;

              case PlayerControl.PAUSED:
//            	  if (stateChangedByRC){
//            		  rcReconnecting(true);
//            		  playPauseMenuItem.setEnabled(false);
//            		  playPauseRCMenuItem.setEnabled(true);}
//            	  else 
            		  break;
            }
          }
        });
      }
      catch (Exception ignored) {/*ignore*/}
    }

    /***************************************************************************
     * Reflect mute state on our menu
     *
     * @param isMuted True when audio playback is muted
     *
     * @see player.PlayerListener#muteChanged(boolean)
     */
    public void muteChanged(final boolean isMuted)
    {
      try
      {
        SwingUtilities.invokeLater(new Runnable() {
          public void run()
          {
            muteMenuItem.setState(isMuted);
          }
        });
      }
      catch (Exception ignored) {/*ignore*/}
    }

    /***************************************************************************
     * This is called to signal optional preferred size from the content.  If we
     * have a preferred size we can enable the menus that allow the size to be
     * set as a ratio of preferred size.  Also, if we autosize to new content we
     * will adjust the player size accordingly.  We use the autoSized flag as we
     * get signalled for this preferred size each time if/when we stop and play
     * the content and for our application we will leave the size at whatever
     * the user wants as long as we don't change to another piece of content.
     * In the latter case we change size only then if the menu preference is
     * selected.
     *
     * @param w      Preferred width or -1 if no preferred size
     * @param h      Preferred height or -1 if no preferred size
     *
     * @see player.PlayerListener#preferSize(int, int)
     */
    public void preferSize(final int w, final int h)
    {
      try
      {
        SwingUtilities.invokeLater(new Runnable() {
          public void run()
          {
            boolean hasPreferredSize = (w > 0 && h > 0);

            size50MenuItem.setEnabled(hasPreferredSize);
            size100MenuItem.setEnabled(hasPreferredSize);
            size200MenuItem.setEnabled(hasPreferredSize);

            if (autosizeMenuItem.getState() && hasPreferredSize)
            {
              if (!autoSized)
              {
                autoSized = true;
                m4Player.setSize(w, h);
                validate();
                pack();
              }
            }

            // Speed scaling is only when we have a preferred size
            //
            speedScaleMenuItem.setEnabled(hasPreferredSize);
          }
        });
      }
      catch (Exception ignored) {/*ignore*/}
    }

    /*****************************************************************************
     * Indicates pixel or meter metrics from presentation
     *
     * @param usePixelMetrics True if using pixel metrics, false is meter metrics
     */
    public void usingMetrics(final boolean usePixelMetrics)
    {
      try
      {
        SwingUtilities.invokeLater(new Runnable() {
          public void run()
          {
            // Scaling is always on in meter metrics so only enable the menu in pixel
            // metrics. This is a choice we could leave the menu always enabled.
            //
            scaleMenuItem.setEnabled(usePixelMetrics);
          }
        });
      }
      catch (Exception ignored) {/*ignore*/}
    }

    /***************************************************************************
     * Content has been opened. Allow any auto resizing to occur and
     * set the window title to reflect the content. This is the first indication
     * we get following content being opened and precedes the preferredSize and
     * usingMetrics indications. Hence this is a suitable point to reset the
     * autosizing flag since the content has changed (it may be the same url if
     * the content is closed and re-opened but we handle that as if it was new
     * content and enable the autosizing again).
     *
     * @param url    The string for the content url.
     *
     * @see player.PlayerListener#urlChanged(java.lang.String)
     */
    public void urlChanged(final String url)
    {
      try
      {
        SwingUtilities.invokeLater(new Runnable() {
          public void run()
          {
            autoSized = false;
            setTitle(url);
          }
        });
      }
      catch (Exception ignored) {/*ignore*/}
    }
  }

  /*****************************************************************************
   * Extends the standard JPanel class. This is just a convenience to allow the
   * painting of the sample 'logo' by setting this as the contentPane.
   *
   */
  private class MyJPanel extends JPanel
  {
    /****************************************************************************
     * This method is just to display the sample player string in the main frame
     * before we add the player renderer component, i.e.  before we Open any
     * content.  or after the component is removed which is after when we Close
     * the content (i.e when the player is not added to the frame)
     *
     * @param g      Graphics context
     */
    public void paintComponent(Graphics g)
    {
      super.paintComponent(g);

      if (!playerAdded)
      {
        Rectangle r = getBounds();
        int w = r.width;
        int h = r.height;

        g.setColor(Color.black);
        g.fillRect(0, 0, w, h);

        Insets i = getInsets();
        w -= i.left + i.right;
        h -= i.top  + i.bottom;

        g.setFont(logoFont);
        FontMetrics fm = g.getFontMetrics();
        int sWidth = fm.stringWidth(kPlayerName);
        int iLeft  = i.left + (w - sWidth)/2;
        int y      = i.top  + h/2;
        g.setColor(Color.blue);
        g.drawString(kPlayerName, iLeft, y);
      }
    }
    //
    private Font logoFont = new Font("Helvetica", Font.BOLD, 16);
  }
  
  class UsaResumeControl extends Thread {	
	  String archivoTarget;
	  
	  
	  UsaResumeControl(String _archivo){
		  this.archivoTarget = _archivo;
	  }
	  
	  public void run() {
		  synchronizedResumeControlHTTP = new SynchronizedResumeControlHTTP(this);
		  synchronizedResumeControlHTTP.irURL(archivoTarget);
		  synchronizedResumeControlHTTP.proceso();
	  }
	  
	  public void rcResume() throws IllegalStateException, IOException{
		rcReconnecting(false);
		setStateChangedByRC(false);  
		m4Player.resume();;
	  } 
	
	  
	  public void rcPause() throws IllegalStateException, IOException{
		  rcReconnecting(true);
		  setStateChangedByRC(true);
	      m4Player.pause(); 
	  } 

  }

public boolean isStateChangedByRC() {
	return stateChangedByRC;
}

public void setStateChangedByRC(boolean stateChangedByRC) {
	this.stateChangedByRC = stateChangedByRC;
}
}
